package com.apes.fn.scm.retailOrder.service.retailProcess.process;

import com.alibaba.fastjson.JSONObject;
import com.apes.crm.business.model.InsuranceCompanyDetail;
import com.apes.fn.business.carAccident.modle.CarAccident;
import com.apes.fn.business.fixedLoss.modle.LossQuotation;
import com.apes.fn.business.fixedLoss.modle.LossReceivedItem;
import com.apes.fn.business.fixedLoss.repository.LossQuotationRepository;
import com.apes.fn.business.fixedLoss.service.FixedLossToForeign;
import com.apes.fn.business.fixedLoss.service.LossReceivedItemService;
import com.apes.fn.scm.insuranceRules.InsuranceRule;
import com.apes.fn.scm.insuranceRules.InsuranceRuleService;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.model.RetailOrderDiscount;
import com.apes.fn.scm.retailOrder.model.RetailOrderPayMethod;
import com.apes.fn.scm.retailOrder.repository.RetailOrderDiscountRepository;
import com.apes.fn.scm.retailOrder.service.retailProcess.ServerAndLossQuotationProcess;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.outbox.OutboxEventService;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.soe.metadata.Scene;
import com.apes.framework.plugin.soe.store.database.repository.SceneRepository;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.party.model.PartyRole;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author wuq
 * @create 2021-05-21 16:55
 */
@Service
public class LossQuotationProcess extends ServerAndLossQuotationProcess {

    @Override
    public void beforeSave(RetailOrder retailOrder) {
        beforeProcess(retailOrder, this::process);

    }

    private void process(RetailOrder retailOrder){
        checkLossQuotation(retailOrder);     // 除了公共判断之外的部分
        addInfo(retailOrder);   // 添加定损相关信息
        updateItem(retailOrder);    // 明细数据处理
    }

    private void checkLossQuotation(RetailOrder saleOrder) {
        for (RetailOrderPayMethod item : saleOrder.getPaymentMethodSet()) {
            if (item.getPaymentMethodType().getId().equals("06")) {
                throw new RuntimeException("定损来源的单据不允许收款为保险充值！");
            }
            if (item.getPaymentMethodType().getId().equals("15")) {
                throw new RuntimeException("定损来源的单据不允许收款为会员红包！");
            }
        }

        // 不能使用异业合作方式
        List<RetailOrderDiscount> retailOrderDiscounts = SpringManager.getBean(RetailOrderDiscountRepository.class).findAllByRetailOrderId(saleOrder.getId());
        if (retailOrderDiscounts.size() > 0) {
            throw new RuntimeException("定损不可以使用任何折扣！");
        }
    }

    private void addInfo(RetailOrder saleOrder){
        String sceneId = "RO002";

        // 在新框架查询数据
        LossQuotation lossQuotation = SpringManager.getBean(LossQuotationRepository.class).findOne(saleOrder.getSource());
        saleOrder.setServiceDept(lossQuotation.getFixedLossDept());         // 添加服务门店
        saleOrder.setInsuranceCompany(lossQuotation.getInsuranceCompany()); // 添加保险公司

        CarAccident carAccident = lossQuotation.queryCarAccident();
        saleOrder.setCaseType(carAccident.getCaseType());                 // 添加案件类型
        saleOrder.setClaimType(carAccident.getCarEvaluations().getClaimType()); // 添加理赔类型
        saleOrder.setHelpReported(carAccident.isHelpReported());          // 车险代报案标记
        saleOrder.setInsuranceReportNumber(carAccident.getReportNumber());   // 保险公司报案号

        // 水泡车流程 协助定损基地字段不能为空
        if ("委托定损".equals(lossQuotation.getOrderType().getName())){
            sceneId = "RO003";
        }

        // 数据检查
        InsuranceRule insuranceRule = SpringManager.getBean(InsuranceRuleService.class)
                .findByDeptAndInsuranceCompany(saleOrder.getServiceDept(), saleOrder.getInsuranceCompany());
        if (Objects.isNull(insuranceRule)) {
            // 没有定损规则，直接基地对保险公司销售

            if (saleOrder.getInsuranceCompany().isCooperation()) {
                throw new RuntimeException("没有找到对应的车险规则，部门：" + saleOrder.getServiceDept().getId() + "，保险公司：" + saleOrder.getInsuranceCompany().getId());
            }

            // 增加定损信息
            lossQuotationInfo(saleOrder, sceneId, saleOrder.getServiceDept().getCompany());

            /** 直接生成对保险公司的分销单 **/
            InsuranceCompanyDetail companyDetail = SpringManager.getBean(FixedLossToForeign.class)
                    .getInsuranceCompanyToClient(saleOrder.getInsuranceCompany(), saleOrder.getServiceDept());
            saleOrder.setSaleCustomer( companyDetail.getClient());
        } else {
            // 定义了定损规则，按照定损规则实现销售

            // 增加定损信息
            lossQuotationInfo(saleOrder, sceneId, insuranceRule.getCompany());

            // 判断基地公司是否能直接对保险公司开票
            if (saleOrder.getServiceDept().getCompany().getId().equals(insuranceRule.getCompany().getId())) {
                /** 直接生成对保险公司的分销单 **/
                InsuranceCompanyDetail companyDetail = SpringManager.getBean(FixedLossToForeign.class)
                        .getInsuranceCompanyToClient(saleOrder.getInsuranceCompany(), saleOrder.getServiceDept());
                saleOrder.setSaleCustomer( companyDetail.getClient());
            } else {
                /** 不能对保险公司开票，找定损规则上面的公司开票 **/
                saleOrder.setSaleCustomer(insuranceRule.getCompany().getParty().getPartyRoleByType("Customer"));
            }
        }
    }

    /**
     * 添加定损相关的字段
     *
     * @param saleOrder 零售单
     * @param sceneId 场景流编码
     */
    private void lossQuotationInfo(RetailOrder saleOrder, String sceneId, PartyRole saleCompany) {

        // 注入场景
        Scene scene = SpringManager.getBean(SceneRepository.class).findOne(sceneId);
        saleOrder.setScene(scene);

        String sourceType = saleOrder.getSourceBusinessType();
        saleOrder.setSourceBusinessType(sourceType);    // 由于存在 SourceBusinessType 为空的情况，将 OrderType值修改之后，可能存在错误，这里重新赋值

        Dept saleOrderDept = saleOrder.getDept();   // 销售部门

        saleOrder.setGetCarDept(saleOrderDept);
        if ("B".equals(saleOrder.getClaimType().getCode())) {
            // 直赔 -- 销售公司
            saleOrder.setPayment(saleCompany);
            for (RetailOrderPayMethod item : saleOrder.getPaymentMethodSet()) {

                // 由于存在多个收款方式，这里只判断 09 其他应收
                if (!item.getPaymentMethodType().getId().equals("09")) continue;

                InsuranceCompanyDetail companyDetail = SpringManager.getBean(FixedLossToForeign.class)
                        .getInsuranceCompanyToClient(saleOrder.getInsuranceCompany(), saleOrder.getServiceDept());
                if (!item.getCustomer().getId().equals(companyDetail.getClient().getId())) {
                    throw new RuntimeException("定损直赔的挂账单位必须与定损单保险公司单位一致！");
                }
            }
            saleOrder.setOrderType("directPay");
        } else {
            // 非直赔 -- 接车门店
            saleOrder.setPayment(saleOrderDept.getCompany());
            saleOrder.setOrderType("noDirectPay");
        }
    }

    @Override
    public void afterSave(RetailOrder retailOrder) {
        retailOrder.setDateDone(new Date());
        callbackServicePlanFinished(retailOrder);

        // 自动归还与减可用数
        if ("RO003".equals(retailOrder.getScene().getId())){
            updateProductAvailable(retailOrder);
        }

    }

    @Override
    public boolean support(String orderType) {
        return "LossQuotation".equals(orderType);
    }

}
